package com.echo.AiManager;


import com.echo.enumeration.ErrorCode;
import com.echo.exception.BusinessException;

import com.zhipu.oapi.ClientV4;
import com.zhipu.oapi.Constants;
import com.zhipu.oapi.service.v4.model.*;
import io.reactivex.Flowable;
import org.springframework.stereotype.Component;

import jakarta.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * 通用 AI 调用能力
 *
 * todo：注意在调用doSyncStableRequest时传入的userMessage可以通过方法进行转为与提示词相同格式的
 *          特定的json串，并且与提示词相结合，这样子才可以
 */
//todo：非流式调用流程：
/*
 * 1.先调用doSyncStableRequest，传入(String systemMessage, String userMessage) 即role和信息
 * 2.自动调用doRequest(systemMessage, userMessage, Boolean.FALSE, STABLE_TEMPERATURE);
 *   将role和usermessge封装起来
 * 3.自动再doStreamRequest(List<ChatMessage> messages, Float temperature) 使得向模型发出请求并返回结果（string）
 *返回的是string
 * */
//todo： 流式调用流程
/*
 * 1.先调用doStreamRequest(String systemMessage, String userMessage, Float temperature) 即role和信息和 温度【稳定程度，这里可以为null】
 * 2.自动doStreamRequest(List<ChatMessage> messages, Float temperature) 返回流式数据
 * 注意这里返回的不是一个string，需要后面去做处理，ssm连接
 * 3. 传给前端：调用StreamResponseService的sendStreamedResponse方法
 * */
//流式调用的示例代码
    /*
     流式调用的示例代码
    * @Deprecated
    @GetMapping("/ai_generate/sse/test")
    public SseEmitter aiGenerateQuestionSSETest(AiGenerateQuestionRequest aiGenerateQuestionRequest,
                                                boolean isVip) {
        ThrowUtils.throwIf(aiGenerateQuestionRequest == null, ErrorCode.PARAMS_ERROR);
        // 获取参数
        Long appId = aiGenerateQuestionRequest.getAppId();
        int questionNumber = aiGenerateQuestionRequest.getQuestionNumber();
        int optionNumber = aiGenerateQuestionRequest.getOptionNumber();
        // 获取应用信息
        App app = appService.getById(appId);
        ThrowUtils.throwIf(app == null, ErrorCode.NOT_FOUND_ERROR);
        // 封装 Prompt
        String userMessage = getGenerateQuestionUserMessage(app, questionNumber, optionNumber);
        // 建立 SSE 连接对象，0 表示永不超时
        SseEmitter sseEmitter = new SseEmitter(0L);
        //todo: AI 生成，SSE 流式返回
        Flowable<ModelData> modelDataFlowable = aiManager.doStreamRequest(GENERATE_QUESTION_SYSTEM_MESSAGE, userMessage, null);
        // 左括号计数器，除了默认值外，当回归为 0 时，表示左括号等于右括号，可以截取
        AtomicInteger counter = new AtomicInteger(0);
        // 拼接完整题目
        StringBuilder stringBuilder = new StringBuilder();
        //todo: 设置线程调度器
        Scheduler scheduler = isVip ? vipScheduler : Schedulers.single();

        // todo:定义数据处理函数，将 ModelData 转换为 JSON 字符串
        Function<ModelData, String> dataProcessor = modelData -> {
            String content = modelData.getChoices().get(0).getDelta().getContent();
            return JSONUtil.toJsonStr(content);  // 将内容转化为 JSON 字符串格式
        };
        // todo:调用通用流式返回方法
        try {
            streamResponseService.sendStreamedResponse(modelDataFlowable, scheduler, dataProcessor, sseEmitter);
        } catch (Exception e) {
            sseEmitter.completeWithError(e);
        }
        return sseEmitter;
    }
    * */
@Component
public class AiManager {

    @Resource
    private ClientV4 clientV4;

    // 稳定的随机数
    private static final float STABLE_TEMPERATURE = 0.05f;

    // 不稳定的随机数
    private static final float UNSTABLE_TEMPERATURE = 0.99f;

    /**
     * 同步请求（答案不稳定）
     *
     * @param systemMessage
     * @param userMessage
     * @return
     */
    public String doSyncUnstableRequest(String systemMessage, String userMessage) {
        return doRequest(systemMessage, userMessage, Boolean.FALSE, UNSTABLE_TEMPERATURE);
    }

    /**
     * 同步请求（答案较稳定）
     *
     * @param systemMessage
     * @param userMessage
     * @return
     */
    public String doSyncStableRequest(String systemMessage, String userMessage) {
        return doRequest(systemMessage, userMessage, Boolean.FALSE, STABLE_TEMPERATURE);
    }

    /**
     * 同步请求
     *
     * @param systemMessage
     * @param userMessage
     * @param temperature
     * @return
     */
    public String doSyncRequest(String systemMessage, String userMessage, Float temperature) {
        return doRequest(systemMessage, userMessage, Boolean.FALSE, temperature);
    }

    /**
     * 通用请求（简化消息传递）
     *
     * @param systemMessage
     * @param userMessage
     * @param stream
     * @param temperature
     * @return
     */
    public String doRequest(String systemMessage, String userMessage, Boolean stream, Float temperature) {
        List<ChatMessage> chatMessageList = new ArrayList<>();

        // 创建一个系统消息并添加到消息列表中
        ChatMessage systemChatMessage = new ChatMessage(ChatMessageRole.SYSTEM.value(), systemMessage);
        chatMessageList.add(systemChatMessage);

        // 创建一个用户消息（即前端传来的消息）并添加到消息列表中
        ChatMessage userChatMessage = new ChatMessage(ChatMessageRole.USER.value(), userMessage);
        chatMessageList.add(userChatMessage);

        // 调用重载的 doRequest 方法，将消息列表、是否流式输出（stream）、温度（temperature）参数传入
        return doRequest(chatMessageList, stream, temperature);
    }


    /**
     * 通用请求
     *
     * @param messages
     * @param stream
     * @param temperature
     * @return
     */
    public String doRequest(List<ChatMessage> messages, Boolean stream, Float temperature) {
        // todo：构建请求
        ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()
                //todo:这里输入模型编码，调用不同的模型
                .model("glm-4-flashx")
                .stream(stream)
                .temperature(temperature)
                .invokeMethod(Constants.invokeMethod)
                .messages(messages)
                .build();
        try {
            ModelApiResponse invokeModelApiResp = clientV4.invokeModelApi(chatCompletionRequest);
            return invokeModelApiResp.getData().getChoices().get(0).toString();
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, e.getMessage());
        }
    }

    /**
     * 通用流式请求（简化消息传递）
     *
     * @param systemMessage
     * @param userMessage
     * @param temperature
     * @return
     */
    public Flowable<ModelData> doStreamRequest(String systemMessage, String userMessage, Float temperature) {
        List<ChatMessage> chatMessageList = new ArrayList<>();
        ChatMessage systemChatMessage = new ChatMessage(ChatMessageRole.SYSTEM.value(), systemMessage);
        chatMessageList.add(systemChatMessage);
        ChatMessage userChatMessage = new ChatMessage(ChatMessageRole.USER.value(), userMessage);
        chatMessageList.add(userChatMessage);
        return doStreamRequest(chatMessageList, temperature);
    }


    /**
     * 通用流式请求
     *
     * @param messages
     * @param temperature
     * @return
     */
    public Flowable<ModelData> doStreamRequest(List<ChatMessage> messages, Float temperature) {
        // 构建请求
        ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()
                .model(Constants.ModelChatGLM4)
                .stream(Boolean.TRUE)
                .temperature(temperature)
                .invokeMethod(Constants.invokeMethod)
                .messages(messages)
                .build();
        try {
            ModelApiResponse invokeModelApiResp = clientV4.invokeModelApi(chatCompletionRequest);
            return invokeModelApiResp.getFlowable();
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, e.getMessage());
        }
    }
}
